package org.kernely.security.ui.group.mgmt;

import java.util.List;

import org.kernely.security.dao.GroupDAO;
import org.kernely.security.persistence.Group;
import org.kernely.security.persistence.Role;
import org.kernely.security.ui.SecurityUIBundle;
import org.kernely.ui.mvp.KernelyEvent;
import org.kernely.ui.mvp.KernelyEventReceiver;
import org.kernely.ui.mvp.KernelyPresenter;
import org.kernely.ui.utils.KernelyDialogWindow;
import org.kernely.ui.utils.KernelyNotification;

import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.terminal.ExternalResource;
import com.vaadin.ui.Button;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Window.Notification;

public class GroupManagementPresenter extends KernelyPresenter<GroupManagementView> implements KernelyEventReceiver{

	/**
	 * Serial Version ID
	 */
	private static final long serialVersionUID = -5744432606883954842L;
	
	/**
	 * The modal subwindow containing all creation/edition forms
	 */
	private Window subwindow;

	/**
	 * @see org.kernely.ui.mvp.IKernelyPresenter#bind()
	 */
	@Override
	public final void bind() {
		SecurityUIBundle.getEventBus().addListener(this);
		listGroups();

		// Add a listener to the table to enable buttons click when a user is selected.
		this.view.getTable().addListener(new Property.ValueChangeListener() {
			private static final long serialVersionUID = -5684256321584269554L;

			/**
			 * If nothing is selected, disable the Edit and Delete buttons.
			 * If a line is selected, buttons are enabled.
			 */
			public void valueChange(ValueChangeEvent event) {
				if (view.getTable().getValue() == null){
					view.getbDeleteGroup().setEnabled(false);
					view.getbEditGroup().setEnabled(false);
				} else {
					view.getbDeleteGroup().setEnabled(true);
					view.getbEditGroup().setEnabled(true);
				}
			}
		});

		// Add a listener to the add button
		this.view.getbAddGroup().addListener(new Button.ClickListener() {
			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				if(!SecurityUIBundle.getSecurityService().getCurrentUser().hasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					displayAddEditGroupWindow(false);
				}
			}
		});

		// Add a listener to the edit button
		this.view.getbEditGroup().addListener(new Button.ClickListener() {
			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				if(!SecurityUIBundle.getSecurityService().getCurrentUser().hasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					displayAddEditGroupWindow(true);
				}
			}
		});

		// Add a listener to the delete button
		this.view.getbDeleteGroup().addListener(new Button.ClickListener() {

			/**
			 * Action when the button is clicked
			 */
			@Override
			public void buttonClick(ClickEvent event) {
				if(!SecurityUIBundle.getSecurityService().getCurrentUser().hasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					deleteGroup();
				}
			}
		});
	}
	
	final private void displayAddEditGroupWindow(boolean editMode){
		GroupManagementWindowPresenter gmwp;
		GroupManagementWindowView gmwv = new GroupManagementWindowView();
		
		if (editMode){
			GroupDAO gdao = GroupDAO.getInstance();
			subwindow = new Window("Kernely - Edit a group ");
			gmwp = new GroupManagementWindowPresenter(gdao.getGroupById((Integer)view.getTable().getValue()));;
		} else {
			subwindow = new Window("Kernely - Add a group ");
			gmwp = new GroupManagementWindowPresenter();

		}
		subwindow.setModal(true);
		subwindow.setResizable(false);
		view.getWindow().addWindow(subwindow);
		subwindow.getContent().setSizeUndefined();
		gmwp.setView(gmwv);
		subwindow.setContent((Layout)gmwp.getView());
		subwindow.setIcon(new ExternalResource("securityUIbundle/images/group_users.png"));
	}

	/**
	 * Delete the selecte group in the table
	 */
	final private void deleteGroup(){
		int id = (Integer)view.getTable().getValue();
		// Get the group
		final GroupDAO gdao = new GroupDAO();
		final Group group = gdao.getGroupById(id);

		// Confirm window
		final KernelyDialogWindow confirm = new KernelyDialogWindow(
				"Kernely - Delete group", "Do you really want to delete the group "
				+ group.getName()
				+ "?",
				KernelyDialogWindow.WARNING_ICON);

		confirm.setConfirmButtonCaption("Yes");
		confirm.setCancelButtonCaption("No");

		// Adding listeners on window's "confirm" buttons click
		confirm.getConfirmButton().addListener(new Button.ClickListener() {
			/**
			 * The action when the "ok" button is clicked
			 */
			@Override
			public void buttonClick(ClickEvent event) {
				// Disable the user in the database
				gdao.deleteGroup(group);
				// Remove the confirm window
				view.getWindow().removeWindow(confirm);
				//Inform the user
				view.getWindow().showNotification(new KernelyNotification("Group " + group.getName() + " deleted.", KernelyNotification.INFO_ICON));
				sendGroupEvent();
				//Refresh the table
				listGroups();
			}
		});

		view.getWindow().addWindow(confirm);
	}

	/**
	 * Sends a ManagementGroupEvent to the event bus.
	 */
	final protected void sendGroupEvent(){
		//Send an event to the event bus to warn groups changes.
		SecurityUIBundle.getEventBus().broadcastEvent(new ManagementGroupEvent(this));
	}

	/**
	 * Re-build the groups table.
	 */
	final private void listGroups(){
		// Only administrators can view groups'list
		if(SecurityUIBundle.getSecurityService().getCurrentUser().hasOneOf(Role.ROLE_ADMINISTRATOR)){
			// Reset the table
			view.getTable().removeAllItems();

			GroupDAO uddao = new GroupDAO();
			List<Group> groups = uddao.getAllGroups();
			for(Group g : groups){
				this.view.getTable().addItem(new Object[] {g.getName(),g.getUsers().size()}, g.getId());
			}
			view.getTable().sort();
		}
	}

	/**
	 * This method handle any KernelyEvent and refresh groups when a ManagementGroupEvent is received.
	 */
	public final void handleKernelyEvent(KernelyEvent event) {
		if (event instanceof ManagementGroupEvent){
			listGroups();
		}
	}

	/**
	 * @see org.kernely.ui.mvp.KernelyPresenter#unset()
	 */
	@Override
	public final void unset() {
		SecurityUIBundle.getEventBus().removeListener(this);
	}

}
